import json

from django.shortcuts import render, redirect
#导包
from django.http import HttpResponse,HttpResponseRedirect,JsonResponse

import re
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView

#导入图片库
#绘画库
from PIL import ImageDraw
#字体库
from PIL import ImageFont
#图片库
from PIL import Image
#随机库
import random
#文件流
import io

import requests

#导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT
import os

#导入原生sql模块
from django.db import connection
from .utils import MysqlFind

import jwt

#导入redis数据库
from .utils import redis

#导入时间模块
import time

#导入公共目录变量
from mydjango.settings import BASE_DIR

#导包
from django.db.models import Q,F

#导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

from myapp.models import User, BlackList, Log

from django.utils.deprecation import MiddlewareMixin

# 导入发邮件方法
from .utils import mail

# 导入发短信方法
from .utils import send_phone_code

# 导入jwt加密和解密方法
from .utils import make_jwt, chack_jwt, base64encode, uploadFile

# 导包自定义权限类
from .check_authority import UserAuthority

import hmac
import base64
from hashlib import sha256
import urllib


# mail('验证码验证服务', '您的验证码是6666，有限期为2分钟', '164850527@qq.com')
# 导入settings的django_url和vue_url
from mydjango.settings import Django_URL, Vue_URL

from .utils import make_password, get_uid
# 导包工厂
from .factory import DingdingFactory, GiteeFactory

# 导包权限验证装饰器
from .check_authority import manage_outer
# 类视图方法使用装饰器必须使用这个方法
from django.utils.decorators import method_decorator

from django.http import QueryDict

# 邮箱码  daxcgjisgimcbheb
# 注册接口
class Register(APIView):
	def post(self, request):
		'''接受参数，'''
		username = request.data.get("username")
		password = request.data.get('password', None)
		password2 = request.data.get('password2', None)
		phone = request.data.get('phone', None)
		photo = request.data.get("photo", None)
		email = request.data.get('email', None)
		email_code = request.data.get('email_code', None)
		# 唯一性验证
		# 1. 验证参数完整性
		if not all([username, password, password2, email, phone, photo]):
			return Response({"code": 999, "msg": "参数不完整"})
		# 2.验证手机号
		if not re.match(r"^1[345678]\d{9}$", phone):
			return Response({"code": 999, "msg": "手机号格式错误"})

		# 3.验证邮箱
		if not re.match(r'^[0-9a-zA-Z_]{0,19}@[0-9a-zA-Z]{1,13}\.[com,cn,net]{1,3}$', email):
			return Response({"code": 999, "msg": "邮箱格式错误"})

		# 4.验证两次密码是否一致
		if not password2 == password:
			return Response({"code": 999, "msg": "两次密码不一致"})

		# 判断邮箱验证码是否正确
		redis_code = redis.get(email).decode()
		if not redis_code == email_code:
			return Response({"code": 999, "msg": "验证码错误"})

		# 4.密码进行加密
		password = make_password(password)

		with open(os.path.join(UPLOAD_ROOT, '', photo), 'rb') as f:
			base64img = base64encode(f)
			upyunimg = uploadFile(photo, f)

		# 5.验证用户名唯一性入库

		'''
		username字段设置uniqe（唯一索引）如果不唯一会报错
		减少读数据库的操作
		'''
		try:

			user = User(username=username, password=password, phone=phone, email=email, photo=photo, base64photo=base64img, upyunimg='http://work-image.test.upcdn.net/'+photo)
			user.save()
			return Response({"code": 200, "msg": "注册成功"})
		except Exception as e:
			print(e)
			return Response({"code": 999, "msg": "注册失败"})


# 获取用户头像
class UserPhoto(APIView):

	def get(self, request):
		uid = get_uid(request)
		user_obj = User.objects.filter(pk=uid).first()
		type = user_obj.photo.split('.')[-1]
		# print(user_obj.base64photo)
		return Response({"code": 200,"type":type, "img": user_obj.base64photo})


# 发送邮箱验证码
class SendEmail(APIView):

	def post(self, request):
		# 获取邮箱
		email = request.data.get('email')
		# 验证邮箱
		if not re.match(r'^[0-9a-zA-Z_]{0,19}@[0-9a-zA-Z]{1,13}\.[com,cn,net]{1,3}$', email):
			return Response({"code": 999, "msg": "邮箱格式错误"})

		# exists = redis.get(email)
		# if exists:
		# 	return Response({"code": 999, "msg": "发送频繁，请稍后"})
		# 发送短信验证码
		num = random.randint(100000, 999999)
		mail('验证码验证服务', '您的验证码是%s，有限期为5分钟' % num, email)

		# redis.setex(email, 60 * 5, num)
		return Response({"code": 200, "msg": "发送成功"})


# 发短信验证
class SendPhone(APIView):

	def post(self, request):
		# 获取手机号
		phone = request.data.get("phone")

		# 防止同一手机号重复发送
		redis_code = redis.get(phone)
		if redis_code:
			return Response({"code": 999, "msg": "发送频繁"})

		# 对手机号校验
		if not phone:
			return Response({"code": 999, "msg": "参数不齐"})
		if not re.match(r"^1[345678]\d{9}$", phone):
			return Response({"code": 999, "msg": "手机号格式错误"})
		# 生成随机数
		num = random.randint(100000, 999999)
		# 发送短信
		try:
			result = send_phone_code(phone, num)
		except Exception as e:
			print(e)
			return Response({"code": 999, "msg": "发送失败"})

		# 发送成功将手机号与验证码存入redis
		redis.setex(phone, 60*2, num)

		return Response({"code": 999, "msg": "发送成功"})


# 登录接口
class UserLogin(APIView):

	def post(self, request):
		# 获取参数
		username = request.data.get("username")
		password = request.data.get("password")
		phone = request.data.get("phone")
		phone_code = request.data.get('phone_code')
		# 判断参数
		if not all([username, password, phone, phone_code]):
			return Response({"code": 999, "msg": "参数不齐"})
		# 判断用户是否存在
		user_obj = User.objects.filter(username=username).first()
		if not user_obj:
			return Response({"code": 999, "msg": "不存在该用户"})
		# 验证密码
		if not make_password(password) == user_obj.password:
			return Response({"code": 999, "msg": "用户名或密码错误"})
		# 判断验证码是否正确
		redis_code = redis.get(phone)
		if not redis_code:
			return Response({"code": 999, "msg": "请先获取验证码"})
		if not phone_code == redis_code.decode():
			return Response({"code": 999, "msg": "验证码错误"})
		# 加密jwt返回
		token = make_jwt({"uid": user_obj.id})
		return Response({"code": 200, "msg": "成功", "data": {"token": token, "username": username, 'uid': user_obj.id}, "uid": user_obj.id, "log": '%s进行登录操作'%username})


# 定义一个公共变量
tripartite = ''
# 三方登录url
def tripartiteUrl(request):
	# 声明修改全局变量
	global tripartite
	name = request.GET.get('name')
	tripartite = name
	if name == 'dingding':
		return redirect(str(DingdingFactory().tripartite_url()))
	elif name == 'gitee':
		return redirect(str(GiteeFactory().tripartite_url()))
	else:
		return Response({"code": "999"})

# 三方回调接口
class TeipartiteBack(APIView):

	def get(self, request):
		# 调用全局变量判断是那个三方登录
		code = request.GET.get("code")
		print(code)
		if tripartite == "dingding":
			return redirect(str(DingdingFactory.tripartite_back(code)))
		elif tripartite == "gitee":
			return redirect(str(GiteeFactory.tripartite_back(code)))


# 用户增删改查接口
class UserView(APIView):
	@method_decorator(manage_outer)
	def get(self, request):
		uid = get_uid(request)

		# 查询该用户的信息，如果是管理元返回所有用户的信息，否则返回自己的
		user_obj = User.objects.all()

		user_data = [{'key': i.id, "uid":i.id, "nickname": i.nickname, "username": i.username, "phone": i.phone, "email": i.email} for i in user_obj]

		return Response({
			"code": 200, "data": user_data,
			"delete": {
				"method": "delete",
				"url": '/myapp/userview/',
				'params': ["uid"]
			},
			'put': {
				"method": "put",
				"url": '/myapp/userview/',
				'params': ['uid', 'username', 'nickname', 'email', 'phone']
			},
		})

	@method_decorator(manage_outer)
	def delete(self, request):
		uid = get_uid(request)
		# 根据前端的jwt的token获取用户uid，获取要删除的用户uid
		delete_uid = request.data.get('uid')

		delete_user = User.objects.get(pk=delete_uid)
		delete_user.delete()
		return Response({
			"code": 200,
			"data": "已删除",
			"uid": uid,
			"log": '对id为%s的用户进行删除' % delete_uid
		})

	@method_decorator(manage_outer)
	def put(self, request):
		# 根据前端的jwt的token获取用户uid
		token = request.META.get("HTTP_AUTHORIZATION")[4:]
		uid = chack_jwt(token).get("uid")

		# 获取参数
		update_uid = request.data.get('uid')
		username = request.data.get("username")
		nickname = request.data.get("nickname")
		phone = request.data.get("phone")
		email = request.data.get("email")
		# 唯一性验证
		# 1. 验证参数完整性
		if not all([username, nickname, email, phone]):
			return Response({"code": 999, "data": "参数不完整"})
		# 2.验证手机号
		if not re.match(r"^1[345678]\d{9}$", phone):
			return Response({"code": 999, "data": "手机号格式错误"})

		# 3.验证邮箱
		if not re.match(r'^[0-9a-zA-Z_]{0,19}@[0-9a-zA-Z]{1,13}\.[com,cn,net]{1,3}$', email):
			return Response({"code": 999, "data": "邮箱格式错误"})

		# 查询该用户的信息，如果是管理员，可以修改任何人，否则只能修改自己的
		user_obj = User.objects.filter(pk=uid)


		update_user = User.objects.get(pk=update_uid)
		try:
			update_user.username = username
		except Exception as e:
			print(e)
			return Response({"code": 999, "data": "用户名重复"})
		update_user.nickname = nickname
		update_user.phone = phone
		update_user.email = email
		update_user.save()
		return Response({
			"code": 200, "data": "修改成功",
			'get': {
				"method": "get",
				"url": "/myapp/userapi"
			},
			'delete': {
				"method":  "delete",
				"url": "myapp/userapi",
				"params": "uid"
			},
			"uid": uid,
			"log": '对id为%s进行删除' % update_uid
		})


class MyMiddleware(MiddlewareMixin):

	def process_request(self, request):
		pass
		# url = request.META.get("PATH_INFO")
		# if url == "/myapp/userview/":
		# 	token = request.META.get("HTTP_AUTHORIZATION", None)
		#
		# 	authority = UserAuthority(token=token, type="用户管理").manage_authority()
		# 	if authority:
		# 		print(111)
		# 		pass
		# 	else:
		# 		return HttpResponse(json.dumps({"code": "999", "data": "您没有权限"}, ensure_ascii=False))


		# uid = 40
		# if 'HTTP_X_FORWARDED_FOR' in request.META:
		# 	ip = request.META.get('HTTP_X_FORWARDED_FOR')
		# else:
		# 	ip = request.META.get('REMOTE_ADDR')
		# print(ip)
		# sql = 'select * from blacklist where ip="%s"' % str(ip)
		# result = MysqlFind(sql).sql_select()
		# print("result:", result,request.META.get('PATH_INFO'))
		# if result:
		# 	print(1)
		# 	return HttpResponse({"code": 999, "data": "您的ip和账号存在异常"}, status=599)
		# # print(result)
		#
		# path = request.META.get('PATH_INFO')
		#
		# # uid = request.META.get('HTTP_UID')
		# # print(uid)
		# url_list = ["/myapp/userlogin/", '/myapp/register/', '/myapp/tripartiteurl/', '/myapp/teipartite_back/']
		# if path not in url_list:
		# 	try:
		# 		token = request.META.get('HTTP_AUTHORIZATION')[4:]
		# 		decode_jwt = jwt.decode(
		# 			token,
		# 			settings.SECRET_KEY,
		# 			algorithms=['HS256'])
		# 	except Exception as e:
		# 		print(e)
		# 		black_obj = BlackList(ip=ip)
		# 		black_obj.save()
		# 		print(2)
		# 		return HttpResponse({"code": 999,"data": "您的ip和账号存在异常"},status=599)


	def process_view(self, request, view_func, view_args, view_kwargs):
		pass

	def process_exception(self, request, exception):
		pass

	def process_response(self, request, response):
		if request.method != 'GET':
			try:
				print('response》》》',response.data)
				res = response.data
				if res.get('code') == 200:
					if res.get("uid"):
						uid = res.get("uid")
					else:
						uid = get_uid(request)
					log = res.get('log')
					log_obj = Log(uid=uid,log=log)
					log_obj.save()
			except Exception as e:
				print(e)
				return response
		return response

		# 添加响应头

		# # 允许你的域名来获取我的数据
		# response['Access-Control-Allow-Origin'] = "*"

		# 允许你携带Content-Type请求头
		# 允许自定义前端可以添加请求头 token 字段
		# response['Access-Control-Allow-Headers'] = "Content-Type,token"

